package com.lyf.scm.admin.domain.service.impl;

import cn.hutool.core.date.DateUtil;
import com.github.pagehelper.PageInfo;
import com.lyf.scm.admin.api.dto.DirectlyStoreDTO;
import com.lyf.scm.admin.api.dto.DirectlyStoreReturnDTO;
import com.lyf.scm.admin.api.dto.PlanResponseDTO;
import com.lyf.scm.admin.domain.remote.allocationservice.facade.DirectlyStoreFacade;
import com.lyf.scm.admin.domain.remote.item.facade.ItemCoreFacade;
import com.lyf.scm.admin.domain.service.DirectlyStoreService;
import com.lyf.scm.admin.domain.util.BaseSearchUtil;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.BaseSearchColumnEnum;
import com.lyf.scm.common.enums.ExcelExportTitleEnum;
import com.lyf.scm.common.enums.ExcelExportTypeEnum;
import com.lyf.scm.common.enums.ResponseMsg;
import com.lyf.scm.common.model.ExcelExportDTO;
import com.lyf.scm.common.model.ExcelExportDataDTO;
import com.lyf.scm.common.model.SalesPlanSelectDTO;
import com.lyf.scm.common.util.AdvancedSearchUtil;
import com.lyf.scm.common.util.ExcelExportUtil;
import com.lyf.scm.common.util.date.MyDateUtil;
import com.lyf.scm.common.util.style.DirectlyStoreCellWriterHandler;
import com.rome.arch.core.exception.RomeException;
import com.rome.user.common.utils.UserContext;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * description:
 * 直营预测计划--门店ServiceImpl
 *
 * @author: haodong
 * @data: 2020/8/29 19:21
 */
@Slf4j
@Service
public class DirectlyStoreServiceImpl implements DirectlyStoreService {

    @Resource
    private DirectlyStoreFacade directlyStoreFacade;

    @Resource
    private ItemCoreFacade itemCoreFacade;


    /**
     * 按条件查询直营预测计划
     *
     * @param directlyStore
     * @return
     */
    @Override
    public PlanResponseDTO<DirectlyStoreReturnDTO> listBySelective(DirectlyStoreDTO directlyStore) {
        //获得最低级品类查询条件
        List<SalesPlanSelectDTO> categorySalesPlanSelect = itemCoreFacade.getSubcategoryCode(directlyStore.getCategoryCodeList());
        //赋值品类搜索条件
        BaseSearchUtil.setSearchFields(directlyStore, null, categorySalesPlanSelect, null);

        //根据日期获取间隔日期集合,没有结束时间，默认14周
        List<Date> dateList = MyDateUtil.getDayDates(directlyStore.getStartTime(), CommonConstants.DAY_SIZE - 1);
        directlyStore.setDateList(dateList);
        directlyStore.setEndTime(MyDateUtil.getLastDate(dateList, null));
        //获取当前角色id(查询角色权限用)
        directlyStore.setCreator(UserContext.getUserId());

        PageInfo<DirectlyStoreReturnDTO> pageInfo = directlyStoreFacade.listPageBySelective(directlyStore);

        PlanResponseDTO<DirectlyStoreReturnDTO> planResponse = new PlanResponseDTO<>();
        planResponse.setInfoList(pageInfo.getList());
        //格式化日期格式
        planResponse.setDateList(MyDateUtil.processDaysDate(dateList, "M.dd"));
        planResponse.setTotal(pageInfo.getTotal());
        return planResponse;
    }

    /**
     * 查询全渠道直营预测计划
     *
     * @param directlyStore
     * @return
     */
    @Override
    public PlanResponseDTO<DirectlyStoreReturnDTO> listAllByDays(DirectlyStoreDTO directlyStore) {
        //获得最低级品类查询条件
        List<SalesPlanSelectDTO> categorySalesPlanSelect = itemCoreFacade.getSubcategoryCode(directlyStore.getCategoryCodeList());
        //赋值品类搜索条件
        BaseSearchUtil.setSearchFields(directlyStore, null, categorySalesPlanSelect, null);

        //获取当前角色id(查询角色权限用)
        directlyStore.setCreator(UserContext.getUserId());

        Date startTime = directlyStore.getStartTime();
        Date endTime = directlyStore.getEndTime();

        List<Date> dateList;
        if (null != endTime) {
            dateList = MyDateUtil.getDayDates(startTime, endTime);
            directlyStore.setDateList(dateList);
        } else {
            //没有结束时间，默认14周
            dateList = MyDateUtil.getDayDates(startTime, CommonConstants.DAY_SIZE - 1);
            directlyStore.setDateList(dateList);
            directlyStore.setEndTime(MyDateUtil.getLastDate(dateList, null));
        }

        List<DirectlyStoreReturnDTO> targetInfoList = directlyStoreFacade.listAllByCycles(directlyStore);
        PlanResponseDTO<DirectlyStoreReturnDTO> planResponse = new PlanResponseDTO<>();
        planResponse.setInfoList(targetInfoList);
        planResponse.setDateList(MyDateUtil.processDaysDate(dateList, "M.dd"));
        return planResponse;
    }

    /**
     * 导出
     * @param excelExportDTO
     * @param type
     * @return
     */
    @Override
    public ExcelExportDataDTO exportExcel(ExcelExportDTO excelExportDTO, Integer type) {
        if (type == null) {
            throw new RomeException(ResponseMsg.FAIL_2005.getCode(), ResponseMsg.FAIL_2005.getMsg());
        }
        DirectlyStoreDTO directly = new DirectlyStoreDTO();
        directly.setChannelCodeList(excelExportDTO.getChannelCodeList());
        directly.setAreaCodeList(excelExportDTO.getAreaCodeList());
        directly.setCategoryCodeList(excelExportDTO.getCategoryCodeList());
        directly.setLayeredCodeList(excelExportDTO.getLayeredCodeList());
        directly.setCreator(UserContext.getUserId());
        //没有结束时间，默认14周
        List<Date> dayDates = MyDateUtil.getDayDates(excelExportDTO.getStartTime(), CommonConstants.DAY_SIZE - 1);
        directly.setDateList(dayDates);
        directly.setStartTime(DateUtil.beginOfMonth(excelExportDTO.getStartTime()));
        directly.setEndTime(MyDateUtil.getLastDate(dayDates, null));
        directly.setUnitType(excelExportDTO.getUnitType());
        //导出当页数据
        if (ExcelExportTypeEnum.CURRENT_PAGE_EXPORT.getType().equals(type)) {
            directly.setPageNum(excelExportDTO.getPageNum());
            directly.setPageSize(excelExportDTO.getPageSize());
        }
        List<Integer> checkedIndex = null;
        //导出勾选
        if (ExcelExportTypeEnum.CHECKED_BOX_EXPORT.getType().equals(type)) {
            directly.setPageNum(excelExportDTO.getPageNum());
            directly.setPageSize(excelExportDTO.getPageSize());
            directly.setRowIndex(excelExportDTO.getRowIndex());
            //获取分页数据
            int start = (directly.getPageNum() - 1) * directly.getPageSize();
            checkedIndex = directly.getRowIndex().stream().map(item -> item + start).collect(Collectors.toList());
        }
        //获得最低级品类查询条件
        List<SalesPlanSelectDTO> categorySalesPlanSelect = itemCoreFacade.getSubcategoryCode(excelExportDTO.getCategoryCodeList());
        //赋值品类搜索条件
        BaseSearchUtil.setSearchFields(directly, null, categorySalesPlanSelect, null);
        //获取导出数据
        List<DirectlyStoreReturnDTO> directlyStoreReturn = directlyStoreFacade.exportExcel(directly, type);
        //获取日期标题
        List<String> dateTitles = MyDateUtil.processDaysDate(dayDates, "MM.dd");
        List<List<Object>> exportDataList = null;
        //指标名称
        List<String> targets = this.getTargetLabel(directlyStoreReturn);
        //全部数据导出
        exportDataList = this.getExcelTargetList(directlyStoreReturn, targets, dateTitles, checkedIndex);
        //获取所有查询条件标识
        List<String> conditions = this.getConditions(directly);
        //获取excel标题 同时返回高级搜索标题的数量
        List<List<String>> heads = new ArrayList<>();
        int mergeCellsColumns = this.setExcelTitles(heads, conditions, dateTitles);
        return ExcelExportUtil.getExcelExportData(mergeCellsColumns, exportDataList, heads, targets.size(), new DirectlyStoreCellWriterHandler());
    }

    /**
     * 更新确认量
     *
     * @param directlyStoreList
     * @param unitType
     * @return
     */
    @Override
    public Boolean updateConfirm(List<DirectlyStoreDTO> directlyStoreList, Long unitType) {
        if (CollectionUtils.isEmpty(directlyStoreList)) {
            throw new RomeException(ResponseMsg.PARAM_ERROR_2015.getCode(),ResponseMsg.PARAM_ERROR_2015.getMsg());
        }
        List<DirectlyStoreDTO> directlyUpdateList = directlyStoreList.stream()
                .map(val -> {
                    val.setCreator(UserContext.getUserId());
                    val.setCreatorName(UserContext.getUserId() == 0 ? "admin" : UserContext.getApplicationUser().getUsername());
                    return val;
                }).collect(Collectors.toList());
        return directlyStoreFacade.updateConfirm(directlyUpdateList, unitType);
    }

    /**
     * 获取指标名称
     *
     * @param salesPlanDirectlyList
     * @return
     */
    private List<String> getTargetLabel(List<DirectlyStoreReturnDTO> salesPlanDirectlyList) {
        List<String> targetsLabel = salesPlanDirectlyList.stream().map(item -> {
            List<String> targets = new ArrayList<>();
            targets.add(item.getForecastLabel());
            targets.add(item.getLastForecastLabel());
            targets.add(item.getForecastFlucteLabel());
            targets.add(item.getForecastFlucteRateLabel());
            // targets.add(item.getGmvTargetLabel());
            targets.add(item.getActualSalesLabel());
            targets.add(item.getConfirmLabel());
            targets.add(item.getLastConfirmLabel());
            targets.add(item.getConfirmTargetLabel());
            targets.add(item.getForecastDifferConfirmLabel());
            targets.add(item.getActualReceiptLabel());
            targets.add(item.getForecastRateConfirmLabel());
            targets.add(item.getRealTimeInventoryLabel());
            return targets;
        }).findFirst().get();
        return targetsLabel;
    }
    /**
     * Excel中的每条数据
     *
     * @param directlyInfo
     * @param targets
     * @param dateTitles
     * @return
     */
    private List<List<Object>> getExcelTargetList(List<DirectlyStoreReturnDTO> directlyInfo, List<String> targets, List<String> dateTitles, List<Integer> checkedIndex) {
        //获取excel数据
        List<List<Object>> exportDataList = new ArrayList<>();
        //组下标
        AtomicInteger groupIndex = new AtomicInteger(0);
        directlyInfo.forEach(item -> {
            if (!CollectionUtils.isEmpty(checkedIndex)) {
                if (!checkedIndex.contains(groupIndex.get())) {
                    groupIndex.incrementAndGet();
                    return;
                }
            }
            for (int i = 0; i < targets.size(); i++) {
                List<Object> itemRow = new ArrayList<>();
                //加入渠道，区域，品类，商品  信息
                this.setExcelRowAdvancedSearchCondition(item, itemRow);
                //加入指标
                itemRow.add(targets.get(i));
                //加入数据
                for (int j = 0; j < dateTitles.size(); j++) {
                    //获取指标集合，这里没有排序，默认使用枚举的顺序
                    switch (i) {
                        case 0:
                            itemRow.add(item.getForecastQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getForecastQty().get(j));
                            break;
                        case 1:
                            itemRow.add(item.getLastForecastQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getLastForecastQty().get(j));
                            break;
                        case 2:
                            itemRow.add(item.getForecastFlucteQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getForecastFlucteQty().get(j));
                            break;
                        case 3:
                            itemRow.add(item.getForecastFlucteRateQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getForecastFlucteRateQty().get(j));
                            break;
                        // case 4:
                        //     itemRow.add(item.getGmvTarget().get(j));
                        //     break;
                        case 4:
                            itemRow.add(item.getActualSales().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getActualSales().get(j));
                            break;
                        case 5:
                            itemRow.add(item.getConfirmQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getConfirmQty().get(j));
                            break;
                        case 6:
                            itemRow.add(item.getLastConfirmQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getLastConfirmQty().get(j));
                            break;
                        case 7:
                            itemRow.add(item.getConfirmTarget().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getConfirmTarget().get(j));
                            break;
                        case 8:
                            itemRow.add(item.getForecastDifferConfirmQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getForecastDifferConfirmQty().get(j));
                            break;
                        case 9:
                            itemRow.add(item.getActualReceiptQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getActualReceiptQty().get(j));
                            break;
                        case 10:
                            itemRow.add(item.getForecastRateConfirmQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getForecastRateConfirmQty().get(j));
                            break;
                        case 11:
                            itemRow.add(item.getRealTimeInventoryQty().get(j).compareTo(BigDecimal.ZERO) == 0 ? "-" : item.getRealTimeInventoryQty().get(j));
                            break;
                        default:
                            break;
                    }
                }
                exportDataList.add(itemRow);
            }
            groupIndex.incrementAndGet();
        });
        return exportDataList;
    }
    /**
     * excel每行数据设置 高级搜索  信息
     *
     * @param directlyReturn
     * @param itemRow
     * @return void
     **/
    private void setExcelRowAdvancedSearchCondition(DirectlyStoreReturnDTO directlyReturn, List<Object> itemRow) {

        if (!StringUtils.isEmpty(directlyReturn.getArea())) {
            itemRow.add(directlyReturn.getArea());
        } else {
            itemRow.add("全国");
        }
        if (!StringUtils.isEmpty(directlyReturn.getCategory())) {
            itemRow.add(directlyReturn.getCategory());
        }
        if (!StringUtils.isEmpty(directlyReturn.getSkuName()) && !StringUtils.isEmpty(directlyReturn.getSkuCode())) {
            itemRow.add(directlyReturn.getSkuCode() + "/" + directlyReturn.getSkuName());
        }
    }
    /**
     * 获取分组条件
     *
     * @param directly
     * @return
     */
    private List<String> getConditions(DirectlyStoreDTO directly) {
        List<String> conditions = new ArrayList<>();
        if (!CollectionUtils.isEmpty(directly.getProvinceCodeList())) {
            conditions.add(BaseSearchColumnEnum.PROVINCE_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getCityCodeList())) {
            conditions.add(BaseSearchColumnEnum.CITY_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getCountyCodeList())) {
            conditions.add(BaseSearchColumnEnum.COUNTY_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getPriCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.PRI_CATEGORY_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getSecCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.SEC_CATEGORY_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getTerCategoryCodeList())) {
            conditions.add(BaseSearchColumnEnum.TER_CATEGORY_CODE.getColumn());
        }
        if (!CollectionUtils.isEmpty(directly.getSkuCodeList())) {
            conditions.add(BaseSearchColumnEnum.SKU_CODE.getColumn());
        }
        return conditions;
    }
    /**
     * 设置导出Excel标题行
     *
     * @param heads
     * @param conditions
     * @param dateTitles
     * @return
     */
    private int setExcelTitles(List<List<String>> heads, List<String> conditions, List<String> dateTitles) {
        //获取高级搜索标题
        this.getExcelAdvancedSearchTitle(heads, conditions);
        int result = heads.size();
        //加入指标标题
        List<String> targetTitle = new ArrayList<>();
        targetTitle.add(ExcelExportTitleEnum.TARGET_TITLE.getTitle());
        heads.add(targetTitle);
        //加入日期标题
        AdvancedSearchUtil.getExcelDateTitle(heads, dateTitles);
        return result;
    }
    /**
     * Excel表头
     *
     * @param heads
     * @param conditions
     */
    private void getExcelAdvancedSearchTitle(List<List<String>> heads, List<String> conditions) {
        setList(heads, ExcelExportTitleEnum.AREA_TITLE.getTitle());
        if (conditions.contains(BaseSearchColumnEnum.PRI_CATEGORY_CODE.getColumn()) ||
                conditions.contains(BaseSearchColumnEnum.SEC_CATEGORY_CODE.getColumn()) ||
                conditions.contains(BaseSearchColumnEnum.TER_CATEGORY_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.CATEGORY_TITLE.getTitle());
        }
        if (conditions.contains(BaseSearchColumnEnum.SKU_CODE.getColumn())) {
            setList(heads, ExcelExportTitleEnum.SKU_TITLE.getTitle());
        }
    }
    /**
     * 获取标题行list
     *
     * @param heads
     * @param title
     */
    private static void setList(List<List<String>> heads, String title) {
        List<String> list = new ArrayList<>();
        list.add(title);
        heads.add(list);
    }
}
